package cn.harry.cabinet.hardware

import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.io.File
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import android.serialport.SerialPort as LicheeSerialPort

/**
 * 串口管理器
 * 负责串口设备的检测、连接和数据传输
 * 
 * 支持功能：
 * - 串口设备枚举和检测
 * - 串口连接管理
 * - 数据收发
 * - 连接状态监控
 * - 自动重连
 */
class SerialPortManager private constructor() {
    
    companion object {
        private const val TAG = "SerialPortManager"
        
        @Volatile
        private var INSTANCE: SerialPortManager? = null
        
        fun getInstance(): SerialPortManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: SerialPortManager().also { INSTANCE = it }
            }
        }
    }
    
    // 串口连接状态
    enum class ConnectionState {
        DISCONNECTED,   // 未连接
        CONNECTING,     // 连接中
        CONNECTED,      // 已连接
        ERROR          // 连接错误
    }
    
    // 串口配置
    data class SerialConfig(
        val devicePath: String,
        val baudRate: Int = 9600,
        val dataBits: Int = 8,
        val stopBits: Int = 1,
        val parity: Int = 0  // 0: NONE, 1: ODD, 2: EVEN
    )
    
    private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    
    // 连接状态
    private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED)
    val connectionState: StateFlow<ConnectionState> = _connectionState.asStateFlow()
    
    // 添加状态变化监听
    private fun notifyConnectionStateChanged(newState: ConnectionState) {
        val oldState = _connectionState.value
        _connectionState.value = newState
        
        if (oldState != newState) {
            val devicePath = currentConfig?.devicePath ?: "未知设备"
            communicationListeners.forEach { listener ->
                try {
                    listener.onConnectionStateChanged(devicePath, oldState, newState)
                } catch (e: Exception) {
                    Log.e(TAG, "通知连接状态变化监听器时发生异常: ${e.message}", e)
                }
            }
        }
    }
    
    // 当前配置
    private var currentConfig: SerialConfig? = null
    
    // 自动恢复状态标志
    private var isAutoRecovering = false
    
    // licheedev串口对象和流
    private var licheeSerialPort: LicheeSerialPort? = null
    private var inputStream: InputStream? = null
    private var outputStream: OutputStream? = null
    
    // 串口通信监听器
    private val communicationListeners = mutableSetOf<SerialCommunicationListener>()
    
    // 读取任务
    private var readJob: Job? = null
    

    /**
     * 连接串口
     */
    suspend fun connect(config: SerialConfig): Boolean = withContext(Dispatchers.IO) {
        // 使用同步块确保连接过程的原子性
        synchronized(this@SerialPortManager) {
            if (_connectionState.value == ConnectionState.CONNECTED) {
                Log.w(TAG, "串口已连接，先断开现有连接")
                disconnect()
            }
            
            if (_connectionState.value == ConnectionState.CONNECTING) {
                Log.w(TAG, "串口正在连接中，请稍候")
                return@withContext false
            }
            
            notifyConnectionStateChanged(ConnectionState.CONNECTING)
            currentConfig = config
            
            try {
                Log.d(TAG, "正在连接串口: ${config.devicePath}, 波特率: ${config.baudRate}")
                
                // 检查设备文件
                val device = File(config.devicePath)
                if (!device.exists()) {
                    throw IOException("串口设备不存在: ${config.devicePath}")
                }
                
                if (!device.canRead() || !device.canWrite()) {
                    throw IOException("串口设备无读写权限: ${config.devicePath}")
                }
                
                // 清理之前的资源
                cleanup()
                
                // 使用licheedev库打开串口
                licheeSerialPort = LicheeSerialPort(
                    File(config.devicePath),
                    config.baudRate
                )
                
                // 获取输入输出流
                inputStream = licheeSerialPort?.inputStream
                outputStream = licheeSerialPort?.outputStream
                
                // 验证流是否创建成功
                if (inputStream == null || outputStream == null) {
                    throw IOException("无法创建串口输入输出流")
                }
                
                // ⚠️ 重要：先更新连接状态为 CONNECTED，再启动读取任务
                // 否则读取循环会因为状态是 CONNECTING 而立即退出
                notifyConnectionStateChanged(ConnectionState.CONNECTED)
                Log.i(TAG, "串口连接成功: ${config.devicePath}")
                
                // 启动数据读取任务（此时状态已是 CONNECTED）
                startReading()
                
                // 通知监听器连接成功
                communicationListeners.forEach { listener ->
                    try {
                        listener.onConnectionSuccess(config.devicePath, config)
                    } catch (e: Exception) {
                        Log.e(TAG, "通知连接成功监听器时发生异常: ${e.message}", e)
                    }
                }
                
                return@withContext true
                
            } catch (e: Exception) {
                Log.e(TAG, "串口连接失败: ${e.message}", e)
                notifyConnectionStateChanged(ConnectionState.ERROR)
                cleanup()
                
                // 通知监听器连接失败
                communicationListeners.forEach { listener ->
                    try {
                        listener.onConnectionFailed(config.devicePath, e.message ?: "未知错误", e)
                    } catch (ex: Exception) {
                        Log.e(TAG, "通知连接失败监听器时发生异常: ${ex.message}", ex)
                    }
                }
                
                return@withContext false
            }
        }
    }
    
    /**
     * 断开串口连接
     */
    fun disconnect() {
        Log.d(TAG, "断开串口连接")
        
        val devicePath = currentConfig?.devicePath ?: "未知设备"
        
        // 停止读取任务
        readJob?.cancel()
        readJob = null
        
        // 清理资源
        cleanup()
        
        notifyConnectionStateChanged(ConnectionState.DISCONNECTED)
        
        // 通知监听器连接关闭
        communicationListeners.forEach { listener ->
            try {
                listener.onConnectionClosed(devicePath, "用户主动断开连接")
            } catch (e: Exception) {
                Log.e(TAG, "通知连接关闭监听器时发生异常: ${e.message}", e)
            }
        }
        
        currentConfig = null
    }

    
    /**
     * 添加串口通信监听器
     */
    fun addCommunicationListener(listener: SerialCommunicationListener) {
        communicationListeners.add(listener)
    }
    
    /**
     * 移除串口通信监听器
     */
    fun removeCommunicationListener(listener: SerialCommunicationListener) {
        communicationListeners.remove(listener)
    }

    
    /**
     * 启动数据读取任务
     */
    private fun startReading() {
        Log.i(TAG, "启动数据读取任务...")
        Log.d(TAG, "当前串口配置: ${currentConfig?.devicePath}")
        Log.d(TAG, "InputStream 状态: ${inputStream != null}")
        Log.d(TAG, "OutputStream 状态: ${outputStream != null}")
        Log.d(TAG, "监听器数量: ${communicationListeners.size}")
        
        readJob = scope.launch {
            val buffer = ByteArray(1024)
            var loopCount = 0
            
            Log.i(TAG, "数据读取协程已启动")
            
            try {
                while (isActive && _connectionState.value == ConnectionState.CONNECTED) {
                    loopCount++

                    // 从串口读取数据
                    val inputStream = this@SerialPortManager.inputStream
                    if (inputStream != null) {
                        val available = inputStream.available()
                        if (available > 0) {
                            Log.d(TAG, "检测到可读数据: $available 字节")
                            
                            val bytesRead = inputStream.read(buffer)
                            if (bytesRead > 0) {
                                val data = buffer.copyOf(bytesRead)
                                
                                Log.i(TAG, "【SerialPortManager】成功读取数据: $bytesRead 字节")
                                Log.d(TAG, "原始数据(HEX): ${data.joinToString(" ") { "%02X".format(it) }}")
                                
                                // 通知通信监听器
                                val devicePath = currentConfig?.devicePath ?: "未知设备"
                                val timestamp = System.currentTimeMillis()
                                
                                Log.d(TAG, "准备通知 ${communicationListeners.size} 个监听器")
                                communicationListeners.forEachIndexed { index, listener ->
                                    try {
                                        Log.d(TAG, "通知监听器 #$index: ${listener.javaClass.simpleName}")
                                        listener.onDataReceived(devicePath, data, timestamp)
                                    } catch (e: Exception) {
                                        Log.e(TAG, "通知监听器 #$index 时发生异常: ${e.message}", e)
                                    }
                                }
                                
                                Log.i(TAG, "数据通知完成")
                            }
                        }
                    } else {
                        Log.e(TAG, "InputStream 为 null！")
                        break
                    }
                    
                    // 没有数据时短暂休眠，避免CPU占用过高
                    delay(10)
                }
                
                Log.w(TAG, "数据读取循环已退出 - isActive: $isActive, 连接状态: ${_connectionState.value}")
            } catch (e: Exception) {
                Log.e(TAG, "数据读取异常: ${e.message}", e)
                if (isActive) {
                    notifyConnectionStateChanged(ConnectionState.ERROR)
                }
            }
        }
        
        Log.i(TAG, "数据读取任务启动完成")
    }
    
    /**
     * 清理资源
     */
    private fun cleanup() {
        try {
            // 先关闭输入输出流
            try {
                inputStream?.close()
            } catch (e: Exception) {
                Log.w(TAG, "关闭输入流时发生异常: ${e.message}")
            }
            
            try {
                outputStream?.close()
            } catch (e: Exception) {
                Log.w(TAG, "关闭输出流时发生异常: ${e.message}")
            }
            
            // 关闭licheedev串口对象
            licheeSerialPort?.let { port ->
                try {
                    port.tryClose()
                    Log.d(TAG, "关闭串口成功")
                } catch (e: Exception) {
                    Log.w(TAG, "关闭串口时发生异常: ${e.message}")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "清理资源时发生异常: ${e.message}")
        } finally {
            // 确保资源被清空
            inputStream = null
            outputStream = null
            licheeSerialPort = null
            
            Log.d(TAG, "资源清理完成")
        }
    }
    
    /**
     * 检查串口是否已连接
     */
    fun isConnected(): Boolean {
        return _connectionState.value == ConnectionState.CONNECTED
    }

    /**
     * 尝试自动恢复连接
     */
    suspend fun tryAutoRecover(): Boolean {
        val config = currentConfig ?: return false
        
        // 防止重复恢复
        if (isAutoRecovering) {
            Log.w(TAG, "自动恢复已在进行中，跳过此次请求")
            return false
        }
        
        isAutoRecovering = true
        
        Log.i(TAG, "尝试自动恢复串口连接: ${config.devicePath}")
        
        return try {
            // 先断开现有连接
            disconnect()
            
            // 等待一段时间再重连
            delay(1000)
            
            // 重新连接
            val success = connect(config)
            
            if (success) {
                Log.i(TAG, "自动恢复连接成功")
            } else {
                Log.e(TAG, "自动恢复连接失败")
            }
            
            success
        } catch (e: Exception) {
            Log.e(TAG, "自动恢复连接异常: ${e.message}", e)
            false
        } finally {
            isAutoRecovering = false
        }
    }
    
    /**
     * 释放资源
     */
    fun release() {
        disconnect()
        scope.cancel()
    }
    
    init {
        Log.d(TAG, "SerialPortManager初始化完成，使用licheedev库")
    }
}